using System;
using System.Collections.Generic;
using System.Text;
using MediaPortal.Dialogs;
using MediaPortal.GUI.Library;
using Action = MediaPortal.GUI.Library.Action;
using Cornerstone.MP;
using System.Text.RegularExpressions;

namespace MyEmulators2
{
    public class Plugin : GUIWindow, ISetupForm
    {
        public static readonly int WINDOW_ID = 2497;

        updatedPresenter newGUIHandler = null;
        private MenuPresenter menuHandler;
        bool firstLoad = true;

        //import options
        Importer importer = null;
        object importStatusLock = new object();
        volatile bool importWaiting = false;
        volatile bool importStopping = false;
        int importCommits = 0;

        ImageSwapper backdrop = null;
        AsyncImageResource cover = null;
        AsyncImageResource backCover = null;
        AsyncImageResource titleScreen = null;
        AsyncImageResource inGameScreen = null;

        [SkinControlAttribute(21)] protected GUIImage fanartControl1 = null;
        [SkinControlAttribute(22)] protected GUIImage fanartControl2 = null;

        [SkinControlAttribute(1232)] protected GUILabelControl fanArtEnabled = null;
        [SkinControlAttribute(1233)] protected GUILabelControl gameArtEnabled = null;

        [SkinControlAttribute(80)] protected GUIAnimation workingAnimation = null;

        //The facade list with emulators and games
        [SkinControlAttribute(50)] protected GUIFacadeControl facade = null;
        //The buttons in the menu to the left
        [SkinControlAttribute(10)] protected GUIButtonControl button_view = null;
        [SkinControlAttribute(11)] protected GUIButtonControl button_mostPlayed = null;
        [SkinControlAttribute(12)] protected GUIButtonControl button_recentlyPlayed = null;
        [SkinControlAttribute(13)] protected GUIButtonControl button_topGraded = null;
        [SkinControlAttribute(14)] protected GUIButtonControl button_moreviews = null;

        public string PluginName()
        {
            return "My Emulators 2";
        }

        public string Description()
        {
            return "My Emulators 2\r\rMy Emulators 2 is a plugin for MediaPortal that allows you to browse and play your emulated games. It supports any number of emulators with all their games. Finding the game you want to play is made easy, and will launch the emulator with the game for you when you want to play it.\r\rMy Emulators 2 also supports a number of extra features. It will show you all kinds of information for the system and games you have. It has images like the box art for the front and back, ingame screen shots, title screen, and fanart. Ratings can be set as well.";
        }
        
        public string Author()
        {
            return "Brownard, Craige1";
        }
        
        public bool CanEnable()
        {
            return true;
        }
        
        public bool DefaultEnabled()
        {
            return true;
        }
        
        public bool HasSetup()
        {
            return true;
        }

        public int GetWindowId()
        {
            return WINDOW_ID;
        }
        
        public override int GetID
        {
            get
            {
                return GetWindowId();
            }
        }

        //Show Configuration
        public void ShowPlugin()
        {
            startUp();
            Conf_GlobalSettings.Instance.IsConfig = true;
            new Conf_Main().ShowDialog();
            Options.Instance.Save();
            Conf_GlobalSettings.Instance.IsConfig = false;
        }

        //Show Plugin
        public override bool Init()
        {
            startUp();
            return Load(GUIGraphicsContext.Skin + @"\myEmulators.xml");
        }

        public override void DeInit()
        {
            if (importer != null)
            {
                new System.Threading.Thread(
                    new System.Threading.ThreadStart(importer.Stop)
                    ).Start();
            }
            base.DeInit();
        }

        void startUp()
        {
            DB.Instance.UpdateDatabase();
            Translator.init();
        }

        public bool GetHome(out string strButtonText, out string strButtonImage, out string strButtonImageFocus, out string strPictureImage)
        {
            strButtonText = Options.Instance.GetStringOption("shownname");
            strButtonImage = String.Empty;
            strButtonImageFocus = String.Empty;
            //It is correct below, but the image must be named hover_myEmulators.png
            strPictureImage = GUIGraphicsContext.Skin + @"\Media\myEmulators.png";
            return true;
        }

        protected override void OnPageLoad()
        {
            base.OnPageLoad();
            if (firstLoad)
            {
                firstLoad = false;

                GUIPropertyManager.SetProperty("#item_title", "");
                GUIPropertyManager.SetProperty("#emulator_title", "");
                GUIPropertyManager.SetProperty("#coverflow_label", "");
                GUIPropertyManager.SetProperty("#game_description", "");
                GUIPropertyManager.SetProperty("#game_yearmade", "");
                GUIPropertyManager.SetProperty("#game_genre", "");
                GUIPropertyManager.SetProperty("#game_company", "");
                GUIPropertyManager.SetProperty("#game_latestplay", "");
                GUIPropertyManager.SetProperty("#game_playcount", "");
                GUIPropertyManager.SetProperty("#game_grade", "0");

                //
                //Image Handlers
                //

                backdrop = new ImageSwapper();
                backdrop.ImageResource.Delay = Options.Instance.GetIntOption("fanartdelay");
                backdrop.PropertyOne = "#fanartpath";

                int delay = Options.Instance.GetIntOption("gameartdelay");

                cover = new AsyncImageResource();
                cover.Delay = delay;
                cover.Property = "#coverpath";

                backCover = new AsyncImageResource();
                backCover.Delay = delay;
                backCover.Property = "#backcoverpath";

                titleScreen = new AsyncImageResource();
                titleScreen.Delay = delay;
                titleScreen.Property = "#titlescreenpath";

                inGameScreen = new AsyncImageResource();
                inGameScreen.Delay = delay;
                inGameScreen.Property = "#ingamescreenpath";

                backdrop.Filename = string.Empty;
                cover.Filename = string.Empty;
                backCover.Filename = string.Empty;
                titleScreen.Filename = string.Empty;
                inGameScreen.Filename = string.Empty;
                //
                //

                newGUIHandler = new updatedPresenter(cover, backCover, titleScreen, inGameScreen);
                menuHandler = new MenuPresenter(newGUIHandler);

                GUIPropertyManager.SetProperty("#plugin_title", Options.Instance.GetStringOption("shownname"));

                bool autorefresh = Options.Instance.GetBoolOption("autorefreshgames");
                bool autoimport = Options.Instance.GetBoolOption("autoimportgames");

                if (autoimport)
                    importer = new Importer(true); //auto start import
                else if (autorefresh)
                    importer = new Importer(false); //only refresh db
                
                if (importer != null)
                {
                    importer.RomStatusChanged += new RomStatusChangedHandler(delegate(object obj, ImportAction action)
                        {

                            if (action == ImportAction.ImportFinished || (action == ImportAction.PendingFilesAdded && !autoimport) || action == ImportAction.NoFilesFound)
                            {
                                lock (importStatusLock)
                                {
                                    if (!importStopping)
                                    {
                                        importStopping = true;
                                        GUIWindowManager.SendThreadMessage(new GUIMessage() { TargetWindowId = WINDOW_ID, SendToTargetWindow = true, Object = ImportAction.ImportFinished });
                                    }
                                }
                            }
                            else if (action == ImportAction.MatchCommited)
                            {
                                GUIWindowManager.SendThreadMessage(new GUIMessage() { TargetWindowId = WINDOW_ID, SendToTargetWindow = true, Object = ImportAction.MatchCommited });
                            }
                            else if (action == ImportAction.ImportWaiting)
                            {
                                lock (importStatusLock)
                                {
                                    if (!importWaiting)
                                    {
                                        importWaiting = true;
                                        GUIWindowManager.SendThreadMessage(new GUIMessage() { TargetWindowId = WINDOW_ID, SendToTargetWindow = true, Object = ImportAction.ImportWaiting });
                                    }
                                }
                            }
                        }
                        );

                    if (workingAnimation != null)
                        workingAnimation.Visible = true;
                    importer.Start();

                    //pause importer during game execution
                    Executor.Instance.StatusChanged += new ExecutorStatusChangedEventHandler(delegate(bool isRunning) 
                        {
                            if (importer == null)
                                return;

                            //game started and we're not paused OR game stopped and we are paused
                            if ((isRunning && !importer.Paused) || (!isRunning && importer.Paused))
                                importer.Pause(); //toggle pause state
                        }
                        );
                }
            }



            DBItem startupItem = null;
            bool launch = false;

            if (!string.IsNullOrEmpty(_loadParameter))
            {
                //Check and load startup parameters

                Regex paramReg = new Regex(@"([A-z]+)\s*:\s*([-]?[A-z0-9]+)");
                List<string> loadParams = new List<string>(_loadParameter.Split(';'));
                foreach (string param in loadParams)
                {
                    Match m = paramReg.Match(param);
                    if (!m.Success)
                        continue;

                    switch (m.Groups[1].Value.ToLower())
                    {
                        case "emulator":
                            int id;
                            if (int.TryParse(m.Groups[2].Value, out id))
                                startupItem = DB.Instance.GetEmulator(id);
                            break;
                        case "rom":
                            //int id;
                            if (int.TryParse(m.Groups[2].Value, out id))
                            {
                                startupItem = DB.Instance.GetGame(id);
                            }
                            break;
                        case "launch":
                            bool tryLaunch;
                            if (bool.TryParse(m.Groups[2].Value, out tryLaunch))
                                launch = tryLaunch;
                            break;
                    }
                }
            }

            button_mostPlayed.Label = Translator.getString(TranslatorString.mostplayed);
            button_recentlyPlayed.Label = Translator.getString(TranslatorString.recentlyplayed);
            button_topGraded.Label = Translator.getString(TranslatorString.topgraded);
            button_moreviews.Label = Translator.getString(TranslatorString.moreviews) + "...";

            backdrop.GUIImageOne = fanartControl1;
            backdrop.GUIImageTwo = fanartControl2;

            if(fanArtEnabled !=null)
                fanArtEnabled.Visible = Options.Instance.GetBoolOption("showfanart"); //update fanart dummy control visibility

            if (gameArtEnabled != null)
                gameArtEnabled.Visible = Options.Instance.GetBoolOption("showgameart"); //update gameart dummy control visibility

            newGUIHandler.Load(facade, button_view, backdrop, startupItem, launch);

            //resume import if previously paused
            if (importer != null && importer.Paused)
                importer.Pause();

        }

        protected override void OnClicked(int controlId, GUIControl control, Action.ActionType actionType)
        {
            base.OnClicked(controlId, control, actionType);
            if (controlId == facade.GetID)
            {
                switch (actionType)
                {
                    case Action.ActionType.ACTION_SELECT_ITEM:
                        newGUIHandler.ItemSelected();
                        break;
                    case Action.ActionType.ACTION_NEXT_ITEM:
                        newGUIHandler.LaunchDocument();
                        break;
                    case Action.ActionType.ACTION_MUSIC_PLAY:
                        newGUIHandler.LaunchArchive();
                        break;
                    case Action.ActionType.ACTION_PAUSE:
                        newGUIHandler.ExtractArchive();
                        break;
                }
            }
            //Layout button
            else if (controlId == button_view.GetID)
            {
                int view = menuHandler.showLayoutDialog(GetID);
                if (view < 0)
                    return;

                newGUIHandler.setLayout(view, true);
            }
            //Most played button
            else if (controlId == button_mostPlayed.GetID)
            {
                newGUIHandler.FillSomeGames("ORDER BY playcount DESC", GameProperty.playcount, 0);
            }
            //Recently played button
            else if (controlId == button_recentlyPlayed.GetID)
            {
                newGUIHandler.FillSomeGames("ORDER BY latestplay DESC", GameProperty.latestplay, 0);
            }
            //Top Graded button
            else if (controlId == button_topGraded.GetID)
            {
                newGUIHandler.FillSomeGames("ORDER BY grade DESC", GameProperty.grade, 0);
            }
            //More views button
            else if (controlId == button_moreviews.GetID)
            {
                if (newGUIHandler.EmulatorSelected())
                    menuHandler.showViewDialog(GetID, true); //We have an emulator to filter DB views against so omit 'All Games' option
                else
                    menuHandler.showViewDialog(GetID);
            }
        }

        public override void OnAction(MediaPortal.GUI.Library.Action action)
        {
            //To allow Esc to go back one level instead of exiting
            if (action.wID == MediaPortal.GUI.Library.Action.ActionType.ACTION_PREVIOUS_MENU)
            {
                if (newGUIHandler.GoBack()) //if true back handled by plugin
                    return;
            }
            base.OnAction(action); //else exit
        }

        protected override void OnShowContextMenu()
        {
            base.OnShowContextMenu();
            newGUIHandler.ShowContextMenu(menuHandler);
        }

        protected override void OnPageDestroy(int new_windowId)
        {
            if (importer != null && !importer.Paused) //stop background importer
            {
                importer.Pause();
            }
            base.OnPageDestroy(new_windowId);
            Options.Instance.Save();
        }

        public override bool OnMessage(GUIMessage message)
        {
            if (message.Object is ImportAction) //partial import results
            {
                ImportAction action = (ImportAction)message.Object;

                if (action == ImportAction.MatchCommited)
                {
                    importCommits++;
                    //only refresh gui if 5 matches have been commited since last refresh.
                    //Avoids excessive updating
                    if (importCommits != 5) 
                        return true;

                    importCommits = 0;
                }
                else if (action == ImportAction.ImportFinished || action == ImportAction.ImportWaiting)
                {
                    if (importer != null)
                        importer.Stop();
                    if (workingAnimation != null)
                        workingAnimation.Visible = false;
                }

                updateDB();

                return true;
            }

            return base.OnMessage(message);
        }

        private void updateDB()
        {
            //foreach (Game game in games)
            //{
                //Logger.LogDebug("Updating game '{0}'", game.Title);
                //DB.saveGame(game);
            //}
            if (newGUIHandler != null)
            {
                newGUIHandler.Refresh(); //update gui with new details
            }
        }
    }
}
